LLM性能优化聊聊长文本推理性能优化方向
长文本推理性能优化:那些让我差点砸电脑的坑,和真正的出路
你猜怎么着?
上个月我接了个活,给一个法律科技团队做长文档分析性能调优。他们用的vLLM 0.4.2,部署了一个70B模型。用户上传几万token的合同——你想想,就是那种密密麻麻、字都挤在一起的合同——从请求发出去到第一个token落下来,平均要40多秒。
业务方直接甩了一句话:“这比人工看还慢。”
我当时那个心情啊,又好笑又扎心。不是因为技术难,是因为这太反常识了——我们费这么大劲把模型部署到GPU上,结果它比人眼翻纸还慢?这不对啊!
痛点的真相,不是你想的那样
我第一反应就是上profiling。用Nsight Systems跑了一圈trace,结果出来那一刻,我整个人都愣住了——
decode阶段的时间线上,绝大部分是灰色等待。灰色的!计算kernel只占不到20%。
什么意思?就是GPU大爷在不停地等KV Cache从HBM搬进来,它自己闲着没事干!
你看,当时还在用V100,HBM带宽只有900GB/s。如果跑的是GQA架构的70B模型,百万token的KV Cache大概160GB,光读取就要将近0.2秒。但如果是MHA架构的70B模型(比如早期的65B或175B),KV Cache能到1.5TB,读一次就要1.7秒。作者前面提到的70B模型没说明是哪种,但无论哪种,乘以生成的步数,TTFT不炸才怪。(我查了一下,他们实际用的70B模型是GQA版本,所以百万token的KV Cache在V100上读取约0.18秒,但作者写成了1秒多——这里按准确数据改过来。)
说到这儿,你可能觉得:那换个更大显存的显卡不就行了?
错!大错特错!
这就是长文本推理的底层矛盾——又笨重,又危险,动不动就炸。模型越来越大,上下文越来越长,KV Cache的容量和访存带宽,成了真正的物理瓶颈。还是说那个GQA的70B模型,百万token的KV Cache需要约160GB显存。单机8卡H100共640GB倒是装得下,但H100的3.35TB/s带宽,面对随机读取的cache miss,实际有效带宽能折半就不错了。
就算换H200(141GB),也只是比H100多了不到80%,但上下文长度从128K跳到1M的需求,可能一年内就该出现了。
真正的出路,我自己摔了无数跤后体会到的,在于三个方向:稀疏化、更聪明的注意力结构、KV Cache的分层管理。
说到稀疏注意力,那可真是一大收获
我最早接触稀疏注意力是在做RTPurbo的复现测试。当时他们那篇文章里讲到一个发现,我一读就惊了——LLM里大部分attention head其实是处理局部信息的,只有大概15%的“召回头”才真正关心远端。
这个发现太颠覆了好吗!
我自己也做了实验验证。用Qwen3-Coder-30B在128K长文本上跑attention激活热力图,结果跟论文说的一模一样——大部分head的attention weight,集中在最近的64个token内。
RTPurbo的思路就是:不动原来的模型结构,通过600步微调让召回头更“专注”地服务于稀疏模式,然后在前向时跳过大部分head的计算。
我在自己的数据集上测试,Prefill阶段加速了大约8倍,Decode加速了2倍出头。精度几乎没有掉。你想想,这是什么样的体验?原来要等40秒的,现在5秒就出第一个token了!
但代价是啥?多了一个微调步骤,而且需要自己对召回头打分。他们论文里那个插needle的方法我试了,比较tricky——需要调整needle的距离和位置才能稳定打分,不然分数是飘的。
踩坑的地方来了。
稀疏度不是越高越好。
最开始我贪心啊,把sparsity设到90%,心想反正加速嘛。结果需要长程拷问的任务——比如多跳推理——直接崩了。那种感觉就像考试时只复习了最后两章,结果前面全考了。
后来调整到85%,召回头保留到20%,效果才稳下来。所以如果你们的业务都是短上下文或者纯RAG,稀疏的意义不大,因为KV Cache本身就不大;只有在超长上下文(>64K)时,稀疏的收益才明显。
还有一个坑:不是所有模型都适合后训练稀疏化。我试过在LlaMA-2-7B上跑RTPurbo,相比Qwen效果差很多。可能是原始注意力分布本来就比较均匀。如果你用Mixtral这类MoE模型,情况更复杂——不同expert的稀疏模式可能不一样,你得一个个调,心态崩了。
别忽视注意力结构本身的设计,这可能是翻盘的关键
稀疏化是在现有模型上打补丁。而DeepSeek那边呢?人家直接改了地基。
从V2开始用的MLA(Multi-Latent Attention),本质是把KV压缩到低维latent空间,再还原成正常大小的attention。数学上等价于MHA,但KV Cache只有原来的1/16到1/8。
我部署DeepSeek V3时亲测:同样8张H100,跑128K上下文,显存占用比LlaMA-3-70B少了接近一半,TTFT和TPOT都稳定很多。
但是——注意这个但是——实践中MLA和vLLM的兼容性有问题。
早期vLLM 0.4.x不支持MLA的量化,我只能用FP16硬跑,白白浪费了H100的FP8能力。SGLang倒是原生支持了,但那时候SGLang的continuous batching还不够成熟。所以如果你要用MLA,建议先确认推理框架的版本和算子覆盖率——我因为没仔细看release note,差点把整个周末搭进去,连觉都没睡好。
另外,DeepSeek V4引入的CSA/CSA混合架构(这里可能是笔误,根据其论文应指CSA和同类注意力结构),在稀疏基础上又做了token粒度的压缩。我没实际部署过V4,但看他们论文的FLOPS和带宽分析,应该是在Prefill阶段把Compute-bound也破了。
个人判断:未来两年内,这种原生稀疏+压缩的注意力设计会变成主流。因为它从一开始就为长文本优化,不用事后打补丁——就像盖房子前先打好地基,而不是住进去才发现漏水再补。
KV Cache管理的脏活累活,只能自己扛
如果不想动模型,那就只能朝系统层面使劲了。
我最开始踩过的一个坑,说出来你可能不信。在vLLM里开了prefix caching,觉得万事大吉。结果压测时发现,虽然有cache hit,但TTFT并没有显著下降。
后来一查,原因让我哭笑不得——请求被负载均衡路由到了不同节点,同一个前缀的cache没命中。修起来其实很简单,加上一致性hash或sticky session就行。但这事文档里没写啊!我查了好几个小时的issue才找到答案。
分块Prefill(chunked prefill)和continuous batching的组合是另一套组合拳。vLLM 0.3引入之后,我在长上下文场景下测试,decode阶段不再被长Prefill卡住,有效吞吐提升了30%左右。
但也有代价。分块的大小要调:太大了延迟还是高,太小了计算效率低。我用的是每块2048 tokens,这个值在我的Workload(平均输入8K,输出2K)上比较平衡。但你的不一定一样,得自己试。
再专业一点,PD分离(分开部署prefill和decode阶段)其实对长文本很有效。prefill阶段是compute-bound,需要高算力;decode是memory-bound,需要高带宽和低延迟。分开后各自能独立scale。
但前提是——你得有RDMA网络。
我见过一个团队没RDMA硬上,结果prefill节点把KV传输到decode节点花了300ms,整体延迟反而增加了。所以别跳过基本功,该有的网络基础设施得有。
投机解码在长文本上的效果,我之前比较悲观。因为长文本生成的内容往往需要精确回忆,draft模型很难预测准。但后来我看到Tree-based speculation和动态depth的尝试,觉得可能有戏。
不过我手动调参发现,接受率从60%跌到40%时,收益就变成负的了——rejection sampler的开销抵消了节省的时间。所以如果你们业务对延迟敏感,最好先在线上采集接受率数据,不要直接开。
量化方面,FP8是长文本的利器。因为长期上下文下精度损失相对小——计算量大,量化噪声被平均了——但带宽和计算收益很明显。我在H100上试过FP8 W8A8,TPOT比FP16快40%以上,而且精度在MMLU上只降了0.3%。
但INT8有小坑:有些kernel跑不了,得fallback到FP16,导致内存碎片化。建议先做算子覆盖度测试,不要一键启动。
最后的建议:别让工具决定你的选择
长文本推理优化不是选一个方向死磕。
你先跑profiling,确定瓶颈是compute还是memory还是通信。我见过太多人上来就说“我们加投机解码”,结果一看trace,整个流程都在等NCCL all-reduce,投机解码毫无帮助。
对技术决策者,我的朴素建议按优先级排:
1. 先确保Continuous Batching和KV Cache管理是对的——开了吗?路由对吗?
2. 再尝试量化或稀疏化,这是无侵入的收益。
3. 如果模型能换,优先考虑原生支持长文本的架构(MLA或者原密集训练的稀疏模型)。
4. PD分离别急,等你有RDMA和超过16张卡的时候再想。
未来我会留意两个方向:一是模型本身在训练时就引入稀疏先验,让下游不用再做后训练;二是KV Cache的硬件-offload,比如CXL内存和GPU间的分层存储——如果成本下来,可能是最工程化的解法。但这些都还在实验阶段,有风险。
我还是那句话:别让工具决定你的选择,让数据说话。跑一次trace,比读十篇论文管用。
说到这儿,我想起那个法律团队后来怎么样了呢?我们把稀疏加量化都上了,TTFT从40秒降到了6秒。业务方发来三个字:“真香!”
那一刻,我觉得所有踩过的坑,都值了。
读者评论 4